// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "stdafx.h"

#include "manager/cef_manager.h"

#include "cef_form.h"
#include "context/config_context.h"


using namespace std;

// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
// automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF
// to the CMake command-line to disable use of the sandbox.
// Uncomment this line to manually enable sandbox support.
// #define CEF_USE_SANDBOX 1

#if defined(CEF_USE_SANDBOX)
// The cef_sandbox.lib static library may not link successfully with all VS
// versions.
#pragma comment(lib, "cef_sandbox.lib")
#endif

class MainThread : public nbase::FrameworkThread
{
public:
    MainThread() : nbase::FrameworkThread("MainThread") {}
    virtual ~MainThread() {}

private:
    virtual void Init() override
    {
        nbase::ThreadManager::RegisterThread(kThreadUI);

        std::wstring sAppDir = nbase::win32::GetCurrentModuleDirectory();
#ifdef _DEBUG
        ui::GlobalManager::Startup(sAppDir + L"\\resources\\", ui::CreateControlCallback(), false, L"themes\\default", L"lang\\zh_CN", L"examples\\cefSimple\\global.xml");
#else
        ui::GlobalManager::OpenResZip(sAppDir + L"\\resources\\themes\\default\\default.zip", "");
        ui::GlobalManager::Startup(L"", ui::CreateControlCallback(), false, L"", L"lang\\zh_CN", L"examples\\cefSimple\\global.xml");
#endif // DEBUG

        wstring dir = nbase::win32::GetCurrentModuleDirectory();
        wstring html = dir + L"\\html\\cef_test.html";
        //html = L"https://sdp-nn.idbhost.com/Ssai?gjkCodes=dismicroecoTXTWN005ysz";
        //html = L"http://sdp-ui.idbhost.com/sdp/file-center/";
        /*html = L"https://www.baidu.com";*/
        CefForm* window = new CefForm(nbase::UTF16ToUTF8(html));
        window->Create(NULL, CefForm::kClassName.c_str(), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, 0, false);
        window->CenterWindow();
        window->ShowWindow();
    };
    virtual void Cleanup() override
    {
        ui::GlobalManager::Shutdown();
        SetThreadWasQuitProperly(true);
        nbase::ThreadManager::UnregisterThread();
    };
};

// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPTSTR lpCmdLine,
                      int nCmdShow) {
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);

#ifdef _DEBUG
  AllocConsole();
  FILE* fp = NULL;
  freopen_s(&fp, "CONOUT$", "w+t", stdout);
  wprintf_s(L"Command:\n%s\n\n", L"");
#endif

  cef::CefManager::GetInstance()->AddCefDllToPath();

  int exit_code;

#if defined(ARCH_CPU_32_BITS)
  // Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
  // stack size. This function must be called at the top of the executable entry
  // point function (`main()` or `wWinMain()`). It is used in combination with
  // the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
  // flag on executable targets. This saves significant memory on threads (like
  // those in the Windows thread pool, and others) whose stack size can only be
  // controlled via the linker flag.
  exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
                                                  lpCmdLine, nCmdShow);
  if (exit_code >= 0) {
    // The fiber has completed so return here.
    return exit_code;
  }
#endif

  std::wstring sAppPath = nbase::win32::GetCurrentModuleDirectory();
#if 1
  CefSettings settings;
  if (!cef::CefManager::GetInstance()->Initialize(sAppPath + L"cef_tmp\\"))
  {
      return 0;
  }
#else
  // Enable High-DPI support on Windows 7 or newer.
  CefEnableHighDPISupport();

  void* sandbox_info = nullptr;

#if defined(CEF_USE_SANDBOX)
  // Manage the life span of the sandbox information object. This is necessary
  // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
  CefScopedSandboxInfo scoped_sandbox;
  sandbox_info = scoped_sandbox.sandbox_info();
#endif

  // Provide CEF with command-line arguments.
  CefMainArgs main_args(hInstance);

  // BrowserProcessApp implements application-level callbacks for the browser process.
  // It will create the first browser instance in OnContextInitialized() after
  // CEF has initialized.
  //CefRefPtr<BrowserProcessApp> app(new BrowserProcessApp);
  CefRefPtr<RenderProcessApp> renderapp(new RenderProcessApp);

  // CEF applications have multiple sub-processes (render, GPU, etc) that share
  // the same executable. This function checks the command-line and, if this is
  // a sub-process, executes the appropriate logic.
  exit_code = CefExecuteProcess(main_args, renderapp, sandbox_info);
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  }

  // Parse command-line arguments for use in this method.
  CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
  command_line->InitFromString(::GetCommandLineW());

  // Specify CEF global settings here.
  CefSettings settings;

  if (command_line->HasSwitch("enable-chrome-runtime")) {
    // Enable experimental Chrome runtime. See issue #2969 for details.
    settings.chrome_runtime = true;
  }

#if !defined(CEF_USE_SANDBOX)
  settings.no_sandbox = true;
#endif

  settings.multi_threaded_message_loop = true;
  settings.background_color = CefColorSetARGB(255, 255, 255, 255);
  
  CefRefPtr<BrowserProcessApp> app(new BrowserProcessApp);
  // Initialize CEF.
  CefInitialize(main_args, settings, app, sandbox_info);
#endif
  MainThread thread;
  thread.RunOnCurrentThreadWithLoop(nbase::MessageLoop::kUIMessageLoop);

  // Shut down CEF.
  CefShutdown();

  return 0;
}
